<?php
declare (strict_types=1);

namespace app\common\model;

use app\common\model\Attribute as AttributeModel;
use app\common\model\AttributeValue as AttributeValueModel;
use app\common\model\RelationAttributeCategory as RelationAttributeCategoryModel;
use Exception;
use think\Collection;
use think\facade\Cache;

class Attribute extends CommonBase
{
    private const _CACHE_KEY = '%s_attributes';

    // 是否为销售属性
    public const IS_SALES_ATTRIBUTE  = 1;
    public const IS_NORMAL_ATTRIBUTE = 2;

    // 是否为图片属性
    public const IS_NOT_PICTURE_ATTRIBUTE = 1;
    public const IS_PICTURE_ATTRIBUTE     = 2;

    public function getAllAttribute(array $where = []): array
    {
        $cacheKey   = sprintf(self::_CACHE_KEY, $this->connection);
        $attributes = Cache::get($cacheKey);
        if (empty($attributes)) {
            $attributes = $this->where(['is_delete' => config('status.mysql.table_normal')])->select()->toArray();
            Cache::set($cacheKey, $attributes);
        }

        $res = [];
        foreach ($attributes as $attribute) {
            $flag = true;
            foreach ($where as $key => $value) {
                if (is_array($value) && count($value) == 3 && $value[1] == 'in' && is_array($value[2])) {
                    if (!in_array($attribute[$value[0]], $value[2])) {
                        $flag = false;
                        break;
                    }
                } else if ($attribute[$key] != $value) {
                    $flag = false;
                    break;
                }
            }

            if ($flag) {
                $res[$attribute['id']] = $attribute;
            }
        }

        return $res;
    }

    public function getAttributeList(int $page = 1, int $limit = 10, array $where = []): Collection
    {
        $where['is_delete'] = config('status.mysql.table_normal');
        $offset             = ($page - 1) * $limit;
        return $this->where($where)->limit($offset, $limit)->select();
    }

    public function getAttributeCount(array $where = []): int
    {
        $where['is_delete'] = config('status.mysql.table_normal');
        return $this->where($where)->count();
    }

    public function findAttributeById(int $id)
    {
        $attributes = $this->getAllAttribute();
        return $attributes[$id];
    }

    public function addAttribute(array $data): bool
    {
        $data['is_delete'] = config('status.mysql.table_normal');
        return (boolean)$this->save($data) && Cache::delete(sprintf(self::_CACHE_KEY, $this->connection));
    }

    public function updateAttribute(int $id, array $data): bool
    {
        $data['updated_at'] = date('Y-m-d H:i:s');
        return (boolean)$this->where(['id' => $id])->save($data) && Cache::delete(sprintf(self::_CACHE_KEY, $this->connection));
    }

    /**
     * @throws Exception
     */
    public function deleteAttribute(int $id): bool
    {
        try {
            $this->startTrans();
            $this->where(['id' => $id])->save(['is_delete' => config('status.mysql.table_delete')]);
            $this->name('attribute_value')->where(['attribute_id' => $id])->save(['is_delete' => config('status.mysql.table_delete')]);
            $this->commit();
            Cache::delete(sprintf(self::_CACHE_KEY, $this->connection));
            return true;
        } catch (Exception $e) {
            $this->rollback();
            throw new Exception($e->getMessage());
        }
    }

    public function clearAttributeCache(): bool
    {
        return Cache::delete(sprintf(self::_CACHE_KEY, $this->connection));
    }

    public function getCategoryAttribute(int $categoryId, array $selectAttributes = []): array
    {
        // 关联的属性
        $hasImageAttribute              = false;
        $imageAttributeId               = 0;
        $attributeIds                   = [];
        $relationAttributeCategoryModel = new RelationAttributeCategoryModel([], $this->connection);
        $relationAttributeCategoryObj   = $relationAttributeCategoryModel->getAllRelationAttributeCategory(['category_id' => $categoryId]);
        $relationAttributeCategory      = $relationAttributeCategoryObj->toArray();
        foreach ($relationAttributeCategory as $v) {
            $attributeIds[] = $v['attribute_id'];
        }

        $attributeValueModel = new AttributeValueModel([], $this->connection);
        $attributeValues     = $attributeValueModel->getAllAttributeValue([['attribute_id', 'in', $attributeIds]]);

        $attributeModel = new AttributeModel([], $this->connection);
        $attributes     = $attributeModel->getAllAttribute([['id', 'in', $attributeIds]]);
        foreach ($attributes as $attribute) {
            if ($attribute['attribute_type'] == AttributeModel::IS_PICTURE_ATTRIBUTE) {
                $hasImageAttribute = true;
                $imageAttributeId  = $attribute['id'];
                break;
            }
        }

        $activeAttributes = [];
        foreach ($attributes as $key => $attribute) {
            $attributeId = $attribute['id'];
            foreach ($attributeValues as $attributeValue) {
                if ($attributeValue['attribute_id'] == $attributeId && count($attributeValue) > 0) {
                    if (!isset($activeAttributes[$attributeId])) {
                        $activeAttributes[$attributeId] = $attribute;
                    }

                    $hasSelected = false;
                    $isSelected  = false;
                    if (isset($selectAttributes[$attributeId])) {
                        $hasSelected             = true;
                        $selectAttributeValueIds = $selectAttributes[$attributeId];
                        $isSelected              = in_array($attributeValue['id'], $selectAttributeValueIds);
                    }

                    $activeAttributes[$attributeId]                                  = array_merge($activeAttributes[$attributeId], ['has_selected' => $hasSelected]);
                    $activeAttributes[$attributeId]['values'][$attributeValue['id']] = array_merge($attributeValue, ['is_selected' => $isSelected]);
                }
            }
        }

        return [
            'hasImageAttribute' => $hasImageAttribute,
            'imageAttributeId'  => $imageAttributeId,
            'attributes'        => $activeAttributes,
        ];
    }
}
